package GeneticAlgorithm_Five;

public class TimetableGA {
    // 已验
    public static void main(String[] args) {
        Timetable timetable = initializeTimetable();
        // 种群100 变异率0.01 交叉率0.9 2个精英个体 锦标赛规模5
        GeneticAlgorithm ga = new GeneticAlgorithm(100, 0.01, 0.9, 2, 5);

        Population population = ga.initPopulation(timetable);

        ga.evalPopulation(population, timetable);

        int generation = 1;

        while (ga.isTerminationConditionMet(generation, 1000) == false
                && ga.isTerminationConditionMet(population) == false) {

            System.out.println("G" + generation + " Best fitness: " + population.getFittest(0).getFitness());

            population = ga.crossoverPopulation(population);

            population = ga.mutatePopulation(population, timetable);

            ga.evalPopulation(population, timetable);
            generation++;

//            ga.coolTemperature();
        }
        timetable.createClasses(population.getFittest(0));
        System.out.println();
        System.out.println("Solution found in " + generation + " generations");
        System.out.println("Final solution fitness: " + population.getFittest(0).getFitness());
        System.out.println("Clashes: " + timetable.calcClashes());


        System.out.println();
        Class classes[] = timetable.getClasses();
        int classIndex = 1;
        for (Class bestClass : classes) {
            System.out.println("Class " + classIndex + ":");
            System.out.println("Module: " +
                    timetable.getModule(bestClass.getModuleId()).getModuleName()+"    || id->:"+bestClass.getModuleId());
            System.out.println("Group: " +
                    timetable.getGroup(bestClass.getGroupId()).getGroupId()+"    || id->:"+bestClass.getGroupId());
            System.out.println("Room: " +
                    timetable.getRoom(bestClass.getRoomId()).getRoomNumber()+"    || id->:"+bestClass.getRoomId());
            System.out.println("Professor: " +
                    timetable.getProfessor(bestClass.getProfessorId()).getProfessorName()+"    || id->:"+bestClass.getProfessorId());
            System.out.println("Time: " +
                    timetable.getTimeslot(bestClass.getTimeslotId()).getTimeslot()+"    || id->:"+bestClass.getTimeslotId());
            System.out.println("-----");
            classIndex++;
        }
        System.out.println();
        System.out.println("Solution found in " + generation + " generations");
        System.out.println("Final solution fitness: " + population.getFittest(0).getFitness());
        System.out.println("Clashes: " + timetable.calcClashes());

    }

    private static Timetable initializeTimetable1() {
        Timetable timetable = new Timetable();

        // 教室表: id主键 name教室名 capacity容纳人数
        timetable.addRoom(1, "A1", 15);
        timetable.addRoom(2, "B1", 30);
        timetable.addRoom(4, "D1", 20);
        timetable.addRoom(5, "F1", 25);


        // 上课时间段安排表 id主键,timeslot时间段
        timetable.addTimeslot(1, "Mon 9:00 - 11:00 ");
        timetable.addTimeslot(2, "Mon 11:00 - 13:00");
        timetable.addTimeslot(3, "Mon 13:00 - 15:00");
        timetable.addTimeslot(4, "Tue 9:00 - 11:00");
        timetable.addTimeslot(5, "Tue 11:00 - 13:00");
        timetable.addTimeslot(6, "Tue 13:00 - 15:00");
        timetable.addTimeslot(7, "Wed 9:00 - 11:00");
        timetable.addTimeslot(8, "Wed 11:00 - 13:00");
        timetable.addTimeslot(9, "Wed 13:00 - 15:00");
        timetable.addTimeslot(10, "Thu 9:00 - 11:00");
        timetable.addTimeslot(11, "Thu 11:00 - 13:00");
        timetable.addTimeslot(12, "Thu 13:00 - 15:00");
        timetable.addTimeslot(13, "Fri 9:00 - 11:00");
        timetable.addTimeslot(14, "Fri 11:00 - 13:00");
        timetable.addTimeslot(15, "Fri 13:00 - 15:00");


        // 教师表:id主键,Name名字
        timetable.addProfessor(1, "Dr P Smith");
        timetable.addProfessor(2, "Mrs E Mitchell");
        timetable.addProfessor(3, "Dr R williams");
        timetable.addProfessor(4, "Mr A Thompson");


        // 课程表：id主键,Code课程码,module课程名,int[]该课能被那些老师id教授
        timetable.addModule(1, "cs1", "Computer Science", new int[]{1, 2});
        timetable.addModule(2, "en1", "English", new int[]{1, 3});
        timetable.addModule(3, "ma1", "Maths", new int[]{1, 2});
        timetable.addModule(4, "ph1", "Physics", new int[]{3, 4});
        timetable.addModule(5, "hi1", "History", new int[]{4});
        timetable.addModule(6, "dr1", "Drama", new int[]{1, 4});


        // 班级表：id主键,Size班级容量大小，new int 里面为改班级要修的课程
        timetable.addGroup(1, 10, new int[]{1, 3, 4});
        timetable.addGroup(2, 30, new int[]{2, 3, 5, 6});
        timetable.addGroup(3, 18, new int[]{3, 4, 5});
        timetable.addGroup(4, 25, new int[]{1, 4});
        timetable.addGroup(5, 20, new int[]{2, 3, 5});
        timetable.addGroup(6, 22, new int[]{1, 4, 5});
        timetable.addGroup(7, 16, new int[]{1, 3});
        timetable.addGroup(8, 18, new int[]{2, 6});
        timetable.addGroup(9, 24, new int[]{1, 6});
        timetable.addGroup(10, 25, new int[]{3, 4});
        return timetable;
    }

    // 初始化 已验
    private static Timetable initializeTimetable() {
        Timetable timetable = new Timetable();

        // 教室表: id主键 name教室名 capacity容纳人数
        timetable.addRoom(1, "A1", 15);
        timetable.addRoom(2, "B1", 30);
        timetable.addRoom(4, "D1", 20);
        timetable.addRoom(5, "F1", 25);


        // 上课时间段安排表 id主键,timeslot时间段
        timetable.addTimeslot(1, "Mon 9:00 - 11:00 ");
        timetable.addTimeslot(2, "Mon 11:00 - 13:00");
        timetable.addTimeslot(3, "Mon 13:00 - 15:00");
        timetable.addTimeslot(4, "Tue 9:00 - 11:00");
        timetable.addTimeslot(5, "Tue 11:00 - 13:00");
        timetable.addTimeslot(6, "Tue 13:00 - 15:00");
        timetable.addTimeslot(7, "Wed 9:00 - 11:00");
        timetable.addTimeslot(8, "Wed 11:00 - 13:00");
        timetable.addTimeslot(9, "Wed 13:00 - 15:00");
        timetable.addTimeslot(10, "Thu 9:00 - 11:00");
        timetable.addTimeslot(11, "Thu 11:00 - 13:00");
        timetable.addTimeslot(12, "Thu 13:00 - 15:00");
        timetable.addTimeslot(13, "Fri 9:00 - 11:00");
        timetable.addTimeslot(14, "Fri 11:00 - 13:00");
        timetable.addTimeslot(15, "Fri 13:00 - 15:00");


        // 教师表:id主键,Name名字
        timetable.addProfessor(1, "Dr P Smith");
        timetable.addProfessor(2, "Mrs E Mitchell");
        timetable.addProfessor(3, "Dr R williams");
        timetable.addProfessor(4, "Mr A Thompson");


        // 课程表：id主键,Code课程码,module课程名,int[]该课能被那些老师id教授
        timetable.addModule(1, "cs1", "Computer Science", new int[]{1, 2});
        timetable.addModule(2, "en1", "English", new int[]{1, 3});
        timetable.addModule(3, "ma1", "Maths", new int[]{1, 2});
        timetable.addModule(4, "ph1", "Physics", new int[]{3, 4});
        timetable.addModule(5, "hi1", "History", new int[]{4});
        timetable.addModule(6, "dr1", "Drama", new int[]{1, 4});


        // 班级表：id主键,Size班级容量大小，new int 里面为改班级要修的课程
        timetable.addGroup(1, 10, new int[]{1, 3, 4});
        timetable.addGroup(2, 30, new int[]{2, 3, 5, 6});
        timetable.addGroup(3, 18, new int[]{3, 4, 5});
        timetable.addGroup(4, 25, new int[]{1, 4});
        timetable.addGroup(5, 20, new int[]{2, 3, 5});
        timetable.addGroup(6, 22, new int[]{1, 4, 5});
        timetable.addGroup(7, 16, new int[]{1, 3});
        timetable.addGroup(8, 18, new int[]{2, 6});
        timetable.addGroup(9, 24, new int[]{1, 6});
        timetable.addGroup(10, 25, new int[]{3, 4});
        return timetable;
    }
}
